package net.piggy.core.socket.parser;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.QueryStringDecoder;
import io.netty.handler.codec.http.multipart.Attribute;
import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder;
import io.netty.handler.codec.http.multipart.InterfaceHttpData;
import io.netty.handler.codec.http.multipart.MixedFileUpload;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;


public class RequestParser {

    private final FullHttpRequest request;

    public RequestParser(FullHttpRequest request) {
        this.request = request;
    }

    /**
     * 简单处理请求路径
     */
    public String getUri() {
        String uri = request.uri();
        int idx = uri.indexOf("?");
        uri = idx > 0 ? uri.substring(0, idx) : uri;
        if (uri.equals("/favicon.ico"))
            return null;
        return uri;
    }

    /**
     * 解析封装请求参数
     * Boolean Byte Short Integer Long Float Double Character String Json
     */
    public JSONObject parse() throws IOException {
        // 获取请求类型
        HttpMethod method = request.method();
        if (HttpMethod.GET == method || HttpMethod.DELETE == method) {
            JSONObject jsonObject = new JSONObject();
            QueryStringDecoder decoder = new QueryStringDecoder(request.uri());
            Map<String, List<String>> parameters = decoder.parameters();
            Set<Map.Entry<String, List<String>>> entries = parameters.entrySet();
            for(Map.Entry<String, List<String>> entry : entries){
                String key = entry.getKey();
                List<String> value = entry.getValue();
                jsonObject.put(key, value);
            }
            return jsonObject;
        } else if (HttpMethod.POST == method || HttpMethod.PUT == method) {
            String contentType = getContentType();
            switch (contentType) {
                case "multipart/form-data":
                case "application/x-www-form-urlencoded":
                    JSONObject jsonObject = new JSONObject();
                    HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(request);
                    List<InterfaceHttpData> bodyHttpData = decoder.getBodyHttpDatas();
                    for(InterfaceHttpData data : bodyHttpData){
                        if(data.getHttpDataType() == InterfaceHttpData.HttpDataType.Attribute) {
                            Attribute attr = (Attribute) data;
                            Object object = jsonObject.get(attr.getName())  ;
                            if(object==null){
                                jsonObject.put(attr.getName(), attr.getValue());
                            }else{
                                if(object instanceof ArrayList){
                                    ((ArrayList<String>) object).add(attr.getValue());
                                }else{
                                    ArrayList<String> arrayList = new ArrayList<>();
                                    arrayList.add(object.toString());
                                    arrayList.add(attr.getValue());
                                    jsonObject.put(attr.getName(), arrayList);
                                }
                            }
                        }
                    }
                    return jsonObject;
                case "application/json":
                    ByteBuf byteBuf = request.content();
                    String content = byteBuf.toString(StandardCharsets.UTF_8);
                    return JSON.parseObject(content);
//                    return JSONObject.parseObject(content);
                case "none":
                    return new JSONObject();
                default:
                    throw new RuntimeException("未实现的协议类型 Content-Type：" + contentType);
            }
        }
        throw new RuntimeException("未实现的请求类型 HttpMethod：" + method);
    }

    /*
     * POST /wg/activity/insert HTTP/1.1
     * Content-Type: application/json
     * User-Agent: PostmanRuntime/7.29.2
     * Postman-Token: xxx
     * Host: localhost:7397
     * Accept-Encoding: gzip, deflate, br
     * Connection: keep-alive
     * Content-Length: 45
     */
    private String getContentType() {
        Optional<Map.Entry<String, String>> header = request.headers().entries().stream().filter(
                val -> val.getKey().equals("Content-Type")
        ).findAny();
        Map.Entry<String, String> entry = header.orElse(null);
        if (null == entry)
            return "none";
        // application/json
        // multipart/form-data
        String contentType = entry.getValue();
        int idx = contentType.indexOf(";");
        if (idx > 0) {
            return contentType.substring(0, idx);
        } else {
            return contentType;
        }
    }

}
